<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>深入理解Java ReentrantLock | 技术小馆</title>
    <link rel="stylesheet" href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css">
    <link rel="stylesheet" href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/mermaid@latest/dist/mermaid.min.js"></script>
    <style>
        body {
            font-family: 'Noto Sans SC', Tahoma, Arial, Roboto, "Droid Sans", "Helvetica Neue", "Droid Sans Fallback", "Heiti SC", "Hiragino Sans GB", Simsun, sans-serif;
            color: #333;
            line-height: 1.6;
            background-color: #f8f9fa;
        }
        
        .hero-gradient {
            background: linear-gradient(135deg, #6e48aa 0%, #9d50bb 100%);
        }
        
        .code-block {
            background-color: #282c34;
            border-radius: 8px;
            padding: 1.5rem;
            position: relative;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
        }
        
        .code-block pre {
            margin: 0;
            overflow-x: auto;
        }
        
        .code-block code {
            font-family: 'Courier New', Courier, monospace;
            color: #abb2bf;
            font-size: 0.9rem;
            line-height: 1.5;
        }
        
        .code-block .copy-btn {
            position: absolute;
            top: 10px;
            right: 10px;
            background-color: rgba(255, 255, 255, 0.1);
            border: none;
            color: #fff;
            padding: 0.25rem 0.5rem;
            border-radius: 4px;
            cursor: pointer;
            transition: all 0.2s;
        }
        
        .code-block .copy-btn:hover {
            background-color: rgba(255, 255, 255, 0.2);
        }
        
        .content-card {
            background-color: white;
            border-radius: 12px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
            padding: 2rem;
            margin-bottom: 2rem;
            transition: transform 0.3s, box-shadow 0.3s;
        }
        
        .content-card:hover {
            transform: translateY(-5px);
            box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
        }
        
        h1, h2, h3, h4 {
            font-family: 'Noto Serif SC', serif;
            font-weight: 600;
            color: #2d3748;
        }
        
        h1 {
            font-size: 2.5rem;
            margin-bottom: 1.5rem;
            position: relative;
            padding-bottom: 1rem;
        }
        
        h1:after {
            content: '';
            position: absolute;
            bottom: 0;
            left: 0;
            width: 60px;
            height: 4px;
            background: linear-gradient(to right, #6e48aa, #9d50bb);
            border-radius: 2px;
        }
        
        h2 {
            font-size: 1.8rem;
            margin-top: 3rem;
            margin-bottom: 1.5rem;
            padding-bottom: 0.5rem;
            border-bottom: 1px solid #e2e8f0;
        }
        
        h3 {
            font-size: 1.4rem;
            margin-top: 2.5rem;
            margin-bottom: 1rem;
        }
        
        p {
            margin-bottom: 1.25rem;
        }
        
        a {
            color: #6e48aa;
            text-decoration: none;
            transition: color 0.2s;
        }
        
        a:hover {
            color: #9d50bb;
        }
        
        .feature-icon {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 50px;
            height: 50px;
            border-radius: 50%;
            background-color: #6e48aa;
            color: white;
            margin-right: 1rem;
            font-size: 1.5rem;
            flex-shrink: 0;
        }
        
        .feature-item {
            display: flex;
            align-items: flex-start;
            margin-bottom: 1.5rem;
        }
        
        .feature-text h4 {
            margin-top: 0;
            margin-bottom: 0.5rem;
        }
        
        .feature-text p {
            margin-bottom: 0;
        }
        
        .nav-item {
            position: relative;
            padding: 0.5rem 0;
            margin-right: 1.5rem;
            cursor: pointer;
        }
        
        .nav-item:after {
            content: '';
            position: absolute;
            bottom: 0;
            left: 0;
            width: 0;
            height: 2px;
            background-color: #6e48aa;
            transition: width 0.3s;
        }
        
        .nav-item:hover:after {
            width: 100%;
        }
        
        .active-nav:after {
            width: 100%;
        }
        
        .comparison-table {
            width: 100%;
            border-collapse: collapse;
        }
        
        .comparison-table th, .comparison-table td {
            padding: 1rem;
            text-align: left;
            border-bottom: 1px solid #e2e8f0;
        }
        
        .comparison-table th {
            background-color: #f7fafc;
            font-weight: 600;
        }
        
        .comparison-table tr:hover {
            background-color: #f8f9fa;
        }
        
        .comparison-table .pros {
            color: #38a169;
        }
        
        .comparison-table .cons {
            color: #e53e3e;
        }
        
        .mermaid-container {
            background-color: white;
            border-radius: 12px;
            padding: 1.5rem;
            margin: 2rem 0;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
        }
        
        footer {
            background-color: #1a202c;
            color: white;
            padding: 3rem 0;
            margin-top: 4rem;
        }
        
        .footer-content {
            max-width: 1200px;
            margin: 0 auto;
            padding: 0 2rem;
        }
        
        .footer-link {
            color: #a0aec0;
            transition: color 0.2s;
        }
        
        .footer-link:hover {
            color: white;
        }
        
        .scroll-top {
            position: fixed;
            bottom: 2rem;
            right: 2rem;
            width: 50px;
            height: 50px;
            border-radius: 50%;
            background-color: #6e48aa;
            color: white;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            opacity: 0;
            transition: opacity 0.3s, transform 0.3s;
            z-index: 100;
        }
        
        .scroll-top.visible {
            opacity: 1;
        }
        
        .scroll-top:hover {
            transform: translateY(-5px);
            background-color: #9d50bb;
        }
    </style>
</head>
<body>
    <!-- Hero Section -->
    <section class="hero-gradient text-white py-20 px-4">
        <div class="max-w-6xl mx-auto">
            <div class="flex flex-col md:flex-row items-center">
                <div class="md:w-2/3 md:pr-16">
                    <div class="flex items-center mb-4">
                        <span class="bg-white text-purple-700 px-3 py-1 rounded-full text-sm font-semibold">Java 并发编程</span>
                    </div>
                    <h1 class="text-4xl md:text-5xl font-bold mb-6 leading-tight">深入理解 ReentrantLock 锁机制</h1>
                    <p class="text-xl opacity-90 mb-8">掌握 Java 并发编程中的高级锁技术，构建高效稳定的多线程应用</p>
                    <div class="flex flex-wrap gap-3">
                        <a href="#concepts" class="bg-white text-purple-700 hover:bg-purple-50 px-6 py-3 rounded-lg font-medium transition-colors">基础概念</a>
                        <a href="#usage" class="bg-purple-800 hover:bg-purple-700 px-6 py-3 rounded-lg font-medium transition-colors border border-white border-opacity-20">核心用法</a>
                        <a href="#source" class="bg-purple-800 hover:bg-purple-700 px-6 py-3 rounded-lg font-medium transition-colors border border-white border-opacity-20">源码分析</a>
                    </div>
                </div>
                <div class="hidden md:block md:w-1/3 mt-10 md:mt-0">
                    <img src="https://cdn-icons-png.flaticon.com/512/226/226777.png" alt="Java Logo" class="w-full max-w-xs mx-auto opacity-90 hover:opacity-100 transition-opacity">
                </div>
            </div>
        </div>
    </section>

    <!-- Main Content -->
    <div class="max-w-6xl mx-auto py-12 px-4">
        <!-- Introduction -->
        <div class="content-card">
            <p class="text-lg mb-6">Java 并发编程中，锁机制是解决线程安全问题的核心工具。相比 synchronized 这个"重量级"的内置锁，JDK 1.5 后引入的 ReentrantLock 提供了更加灵活和强大的锁机制。作为一名 Java 开发者，深入理解 ReentrantLock 的工作原理和使用技巧，不仅能帮助你构建高效稳定的并发应用，还能在面试中脱颖而出。</p>
            
            <div class="grid md:grid-cols-3 gap-8 mt-8">
                <div class="feature-item">
                    <div class="feature-icon">
                        <i class="fas fa-lock-open"></i>
                    </div>
                    <div class="feature-text">
                        <h4>灵活控制</h4>
                        <p>提供公平锁、非公平锁选项，支持尝试获取锁和超时机制</p>
                    </div>
                </div>
                <div class="feature-item">
                    <div class="feature-icon">
                        <i class="fas fa-project-diagram"></i>
                    </div>
                    <div class="feature-text">
                        <h4>条件变量</h4>
                        <p>支持多个条件变量，比 synchronized 的单一等待队列更灵活</p>
                    </div>
                </div>
                <div class="feature-item">
                    <div class="feature-icon">
                        <i class="fas fa-tachometer-alt"></i>
                    </div>
                    <div class="feature-text">
                        <h4>高性能</h4>
                        <p>非公平模式提供更高的吞吐量，适合大多数场景</p>
                    </div>
                </div>
            </div>
        </div>

        <!-- Table of Contents Navigation -->
        <div class="sticky top-0 bg-white shadow-sm rounded-lg p-4 mb-8 z-10">
            <div class="flex overflow-x-auto">
                <a href="#concepts" class="nav-item font-medium text-gray-700 hover:text-purple-700">基础概念</a>
                <a href="#usage" class="nav-item font-medium text-gray-700 hover:text-purple-700">核心用法</a>
                <a href="#source" class="nav-item font-medium text-gray-700 hover:text-purple-700">源码分析</a>
                <a href="#practice" class="nav-item font-medium text-gray-700 hover:text-purple-700">实战应用</a>
                <a href="#best-practices" class="nav-item font-medium text-gray-700 hover:text-purple-700">最佳实践</a>
            </div>
        </div>

        <!-- Section 1: Basic Concepts -->
        <section id="concepts" class="content-card">
            <h2>一、ReentrantLock 基础概念</h2>
            <p>ReentrantLock 是 Java 并发包（java.util.concurrent.locks）中的一个可重入锁实现，它提供了与 synchronized 相同的互斥性和内存可见性保证，同时还扩展了更丰富的功能。</p>
            
            <h3>1.1 什么是可重入锁？</h3>
            <p>可重入锁允许同一个线程多次获取同一把锁，而不会产生死锁。简单来说，如果一个线程已经持有了锁，那么它可以再次获取该锁而不被阻塞。</p>
            
            <div class="code-block mt-6 mb-8">
                <button class="copy-btn" onclick="copyCode(this)"><i class="fas fa-copy"></i></button>
                <pre><code>public class ReentrantDemo {
    private final ReentrantLock lock = new ReentrantLock();
    
    public void outer() {
        lock.lock();  // 第一次获取锁
        try {
            System.out.println("进入 outer 方法");
            inner();  // 调用 inner 方法
        } finally {
            lock.unlock();  // 释放锁
        }
    }
    
    public void inner() {
        lock.lock();  // 第二次获取锁（重入）
        try {
            System.out.println("进入 inner 方法");
        } finally {
            lock.unlock();  // 释放锁
        }
    }
    
    public static void main(String[] args) {
        ReentrantDemo demo = new ReentrantDemo();
        demo.outer();
    }
}</code></pre>
            </div>
            
            <h3>1.2 ReentrantLock 与 synchronized 的区别</h3>
            <table class="comparison-table">
                <thead>
                    <tr>
                        <th>特性</th>
                        <th>ReentrantLock</th>
                        <th>synchronized</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td>实现方式</td>
                        <td>Java代码实现，基于AQS</td>
                        <td>JVM内置实现</td>
                    </tr>
                    <tr>
                        <td>锁获取</td>
                        <td class="pros">支持尝试获取锁、超时获取、可中断获取</td>
                        <td class="cons">只能阻塞等待</td>
                    </tr>
                    <tr>
                        <td>公平性</td>
                        <td class="pros">支持公平锁和非公平锁</td>
                        <td class="cons">仅非公平锁</td>
                    </tr>
                    <tr>
                        <td>条件变量</td>
                        <td class="pros">支持多个Condition</td>
                        <td class="cons">只能有一个等待队列</td>
                    </tr>
                    <tr>
                        <td>性能</td>
                        <td>高竞争下性能更好</td>
                        <td>低竞争下性能更好</td>
                    </tr>
                </tbody>
            </table>
            
            <div class="mermaid-container">
                <div class="mermaid">
                    graph LR
                    A[Lock接口] --> B[ReentrantLock]
                    B --> C[公平锁 FairSync]
                    B --> D[非公平锁 NonfairSync]
                    C & D --> E[AbstractQueuedSynchronizer]
                    E --> F[同步状态 state]
                    E --> G[等待队列 CLH]
                </div>
            </div>
        </section>

        <!-- Section 2: Core Usage -->
        <section id="usage" class="content-card">
            <h2>二、ReentrantLock 的核心用法</h2>
            
            <h3>2.1 基本用法</h3>
            <p>ReentrantLock 的标准使用模式是在 try-finally 块中确保锁的释放：</p>
            
            <div class="code-block mt-6 mb-8">
                <button class="copy-btn" onclick="copyCode(this)"><i class="fas fa-copy"></i></button>
                <pre><code>private final ReentrantLock lock = new ReentrantLock();

public void method() {
    // 获取锁
    lock.lock();
    try {
        // 临界区代码
        // ...
    } finally {
        // 确保锁被释放
        lock.unlock();
    }
}</code></pre>
            </div>
            
            <h3>2.2 公平锁与非公平锁</h3>
            <p>ReentrantLock 支持公平锁和非公平锁两种模式：</p>
            
            <div class="code-block mt-6 mb-8">
                <button class="copy-btn" onclick="copyCode(this)"><i class="fas fa-copy"></i></button>
                <pre><code>// 默认是非公平锁
ReentrantLock nonFairLock = new ReentrantLock();

// 创建公平锁
ReentrantLock fairLock = new ReentrantLock(true);</code></pre>
            </div>
            
            <div class="grid md:grid-cols-2 gap-6 mt-6">
                <div class="p-4 border border-gray-200 rounded-lg">
                    <h4 class="text-green-600 mb-2"><i class="fas fa-balance-scale mr-2"></i>公平锁</h4>
                    <ul class="list-disc pl-5 space-y-1">
                        <li>线程按照请求顺序获取锁</li>
                        <li>等待时间最长的线程优先获取锁</li>
                        <li>吞吐量相对较低</li>
                        <li>适合对公平性要求高的场景</li>
                    </ul>
                </div>
                <div class="p-4 border border-gray-200 rounded-lg">
                    <h4 class="text-blue-600 mb-2"><i class="fas fa-bolt mr-2"></i>非公平锁</h4>
                    <ul class="list-disc pl-5 space-y-1">
                        <li>线程可以"插队"获取锁</li>
                        <li>不保证等待时间最长的线程优先获取锁</li>
                        <li>吞吐量通常更高</li>
                        <li>适合大多数高性能场景</li>
                    </ul>
                </div>
            </div>
            
            <h3>2.3 高级特性演示</h3>
            
            <h4>2.3.1 可中断锁获取</h4>
            <div class="code-block mt-6 mb-8">
                <button class="copy-btn" onclick="copyCode(this)"><i class="fas fa-copy"></i></button>
                <pre><code>import java.util.concurrent.locks.ReentrantLock;

public class InterruptibleLockExample {
    private final ReentrantLock lock = new ReentrantLock();
    
    public void lockInterruptibly() {
        Thread currentThread = Thread.currentThread();
        System.out.println(currentThread.getName() + " 尝试获取锁");
        
        try {
            // 可中断地获取锁
            lock.lockInterruptibly();
            try {
                System.out.println(currentThread.getName() + " 获取到锁");
                // 模拟耗时操作
                Thread.sleep(5000);
            } finally {
                lock.unlock();
                System.out.println(currentThread.getName() + " 释放了锁");
            }
        } catch (InterruptedException e) {
            System.out.println(currentThread.getName() + " 等待锁的过程被中断");
        }
    }
    
    public static void main(String[] args) throws InterruptedException {
        InterruptibleLockExample example = new InterruptibleLockExample();
        
        // 创建一个线程并启动
        Thread thread1 = new Thread(() -> example.lockInterruptibly(), "线程1");
        thread1.start();
        
        // 确保线程1先获取到锁
        Thread.sleep(100);
        
        // 创建第二个线程并启动
        Thread thread2 = new Thread(() -> example.lockInterruptibly(), "线程2");
        thread2.start();
        
        // 让线程2等待一段时间，然后中断它
        Thread.sleep(1000);
        thread2.interrupt();
        
        // 等待线程完成
        thread1.join();
        thread2.join();
    }
}</code></pre>
            </div>
            
            <h4>2.3.2 尝试获取锁与超时获取</h4>
            <div class="code-block mt-6 mb-8">
                <button class="copy-btn" onclick="copyCode(this)"><i class="fas fa-copy"></i></button>
                <pre><code>import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

public class TryLockExample {
    private final ReentrantLock lock = new ReentrantLock();
    
    public void nonBlockingMethod() {
        boolean acquired = lock.tryLock();
        if (acquired) {
            try {
                System.out.println(Thread.currentThread().getName() + " 获取到了锁");
                // 临界区代码
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {
                lock.unlock();
                System.out.println(Thread.currentThread().getName() + " 释放了锁");
            }
        } else {
            System.out.println(Thread.currentThread().getName() + " 无法获取锁，执行替代逻辑");
            // 执行替代逻辑
        }
    }
    
    public void timeoutMethod() {
        try {
            boolean acquired = lock.tryLock(3, TimeUnit.SECONDS);
            if (acquired) {
                try {
                    System.out.println(Thread.currentThread().getName() + " 在超时前获取到了锁");
                    // 临界区代码
                    Thread.sleep(1000);
                } finally {
                    lock.unlock();
                    System.out.println(Thread.currentThread().getName() + " 释放了锁");
                }
            } else {
                System.out.println(Thread.currentThread().getName() + " 等待锁超时");
            }
        } catch (InterruptedException e) {
            System.out.println(Thread.currentThread().getName() + " 等待过程被中断");
        }
    }
    
    public static void main(String[] args) throws InterruptedException {
        TryLockExample example = new TryLockExample();
        
        // 测试tryLock
        Thread thread1 = new Thread(example::nonBlockingMethod, "tryLock线程");
        thread1.start();
        
        // 确保第一个线程获取到锁
        Thread.sleep(100);
        
        Thread thread2 = new Thread(example::nonBlockingMethod, "tryLock线程2");
        thread2.start();
        
        thread1.join();
        thread2.join();
        
        System.out.println("===== 测试带超时的tryLock =====");
        
        Thread thread3 = new Thread(() -> {
            example.lock.lock();
            try {
                System.out.println(Thread.currentThread().getName() + " 获取锁并持有5秒");
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {
                example.lock.unlock();
            }
        }, "长时间持有锁的线程");
        thread3.start();
        
        // 确保thread3获取到锁
        Thread.sleep(100);
        
        Thread thread4 = new Thread(example::timeoutMethod, "超时尝试线程");
        thread4.start();
        
        thread3.join();
        thread4.join();
    }
}</code></pre>
            </div>
            
            <h4>2.3.3 使用条件变量（Condition）</h4>
            <div class="code-block mt-6 mb-8">
                <button class="copy-btn" onclick="copyCode(this)"><i class="fas fa-copy"></i></button>
                <pre><code>import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class ConditionExample {
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition notEmpty = lock.newCondition();
    private final Condition notFull = lock.newCondition();
    private final int capacity = 10;
    private int count = 0;
    
    public void produce() throws InterruptedException {
        lock.lock();
        try {
            while (count == capacity) {
                System.out.println("缓冲区满，生产者等待");
                notFull.await();  // 等待不满条件
            }
            
            count++;
            System.out.println("生产者生产了一个产品，当前数量: " + count);
            
            // 通知消费者可以消费了
            notEmpty.signal();
        } finally {
            lock.unlock();
        }
    }
    
    public void consume() throws InterruptedException {
        lock.lock();
        try {
            while (count == 0) {
                System.out.println("缓冲区空，消费者等待");
                notEmpty.await();  // 等待不空条件
            }
            
            count--;
            System.out.println("消费者消费了一个产品，当前数量: " + count);
            
            // 通知生产者可以生产了
            notFull.signal();
        } finally {
            lock.unlock();
        }
    }
    
    public static void main(String[] args) {
        ConditionExample example = new ConditionExample();
        
        // 创建生产者线程
        Thread producer = new Thread(() -> {
            try {
                for (int i = 0; i < 20; i++) {
                    example.produce();
                    Thread.sleep(100);  // 生产速度慢一些
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
        
        // 创建消费者线程
        Thread consumer = new Thread(() -> {
            try {
                for (int i = 0; i < 20; i++) {
                    example.consume();
                    Thread.sleep(200);  // 消费速度更慢
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
        
        // 启动线程
        producer.start();
        consumer.start();
        
        // 等待线程结束
        try {
            producer.join();
            consumer.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}</code></pre>
            </div>
        </section>

        <!-- Section 3: Source Code Analysis -->
        <section id="source" class="content-card">
            <h2>三、ReentrantLock 源码分析</h2>
            <p>ReentrantLock 的内部实现基于 AQS（AbstractQueuedSynchronizer）框架，通过内部类 Sync 及其子类 FairSync 和 NonfairSync 实现不同的锁策略。</p>
            
            <h3>3.1 ReentrantLock 的内部结构</h3>
            <div class="code-block mt-6 mb-8">
                <button class="copy-btn" onclick="copyCode(this)"><i class="fas fa-copy"></i></button>
                <pre><code>public class ReentrantLock implements Lock, java.io.Serializable {
    // 同步器，所有锁操作都委托给它
    private final Sync sync;
    
    // 抽象同步器类，继承自AQS
    abstract static class Sync extends AbstractQueuedSynchronizer {
        // 尝试非公平获取锁
        final boolean nonfairTryAcquire(int acquires) {
            // ...
        }
        
        // 尝试释放锁
        protected final boolean tryRelease(int releases) {
            // ...
        }
        
        // 判断是否被当前线程持有
        protected final boolean isHeldExclusively() {
            // ...
        }
    }
    
    // 非公平锁实现
    static final class NonfairSync extends Sync {
        // ...
    }
    
    // 公平锁实现
    static final class FairSync extends Sync {
        // ...
    }
}</code></pre>
            </div>
            
            <h3>3.2 加锁流程分析</h3>
            <p>以非公平锁为例，当调用 ReentrantLock.lock() 方法时，会执行以下流程：</p>
            
            <div class="code-block mt-6 mb-8">
                <button class="copy-btn" onclick="copyCode(this)"><i class="fas fa-copy"></i></button>
                <pre><code>// ReentrantLock 类中的 lock 方法
public void lock() {
    sync.lock();
}

// NonfairSync 中的 lock 方法
final void lock() {
    // 1. 首先尝试通过 CAS 获取锁
    if (compareAndSetState(0, 1))
        // 获取成功，设置当前线程为拥有独占访问权限的线程
        setExclusiveOwnerThread(Thread.currentThread());
    else
        // 获取失败，执行 AQS 的 acquire 方法
        acquire(1);
}

// AQS 中的 acquire 方法
public final void acquire(int arg) {
    // 尝试获取锁，如果失败则进入队列等待
    if (!tryAcquire(arg) && 
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}

// NonfairSync 中的 tryAcquire 方法
protected final boolean tryAcquire(int acquires) {
    return nonfairTryAcquire(acquires);
}

// Sync 中的 nonfairTryAcquire 方法
final boolean nonfairTryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    // 如果锁未被持有
    if (c == 0) {
        // 尝试通过 CAS 获取锁
        if (compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(current);
            return true;
        }
    }
    // 如果当前线程已经持有锁（重入）
    else if (current == getExclusiveOwnerThread()) {
        // 增加重入次数
        int nextc = c + acquires;
        // 检查溢出
        if (nextc < 0)
            throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    // 获取锁失败
    return false;
}</code></pre>
            </div>
            
            <div class="mermaid-container">
                <div class="mermaid">
                    sequenceDiagram
                    participant T as Thread
                    participant RL as ReentrantLock
                    participant NF as NonfairSync
                    participant AQS as AbstractQueuedSynchronizer
                    
                    T->>RL: lock()
                    RL->>NF: lock()
                    NF->>AQS: compareAndSetState(0,1)
                    alt CAS 成功
                        NF->>AQS: setExclusiveOwnerThread(Thread.currentThread())
                    else CAS 失败
                        NF->>AQS: acquire(1)
                        AQS->>NF: tryAcquire(1)
                        NF->>AQS: nonfairTryAcquire(1)
                        alt 获取成功
                            NF-->>AQS: true
                        else 获取失败
                            AQS->>AQS: addWaiter(Node.EXCLUSIVE)
                            AQS->>AQS: acquireQueued(node, arg)
                        end
                    end
                </div>
            </div>
            
            <h3>3.3 公平锁与非公平锁源码对比</h3>
            <p>非公平锁和公平锁的主要区别在于 tryAcquire 方法的实现：</p>
            
            <div class="code-block mt-6 mb-8">
                <button class="copy-btn" onclick="copyCode(this)"><i class="fas fa-copy"></i></button>
                <pre><code>// FairSync 中的 tryAcquire 方法
protected final boolean tryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {
        // 关键区别：检查是否有线程在等待队列中
        if (!hasQueuedPredecessors() && 
            compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(current);
            return true;
        }
    }
    else if (current == getExclusiveOwnerThread()) {
        int nextc = c + acquires;
        if (nextc < 0)
            throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    return false;
}</code></pre>
            </div>
            
            <p>关键区别在于公平锁会通过 <code>hasQueuedPredecessors()</code> 方法检查是否有线程已经在队列中等待，如果有则当前线程不会尝试获取锁，而是进入队列等待，这保证了等待时间最长的线程优先获取锁。</p>
        </section>

        <!-- Section 4: Practical Applications -->
        <section id="practice" class="content-card">
            <h2>四、ReentrantLock 实战应用</h2>
            
            <h3>4.1 实现高效的读写缓存</h3>
            <div class="code-block mt-6 mb-8">
                <button class="copy-btn" onclick="copyCode(this)"><i class="fas fa-copy"></i></button>
                <pre><code>import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

public class ConcurrentCache<K, V> {
    private final Map<K, V> cache = new HashMap<>();
    private final ReentrantLock lock = new ReentrantLock();
    
    public V get(K key) {
        lock.lock();
        try {
            return cache.get(key);
        } finally {
            lock.unlock();
        }
    }
    
    public void put(K key, V value) {
        lock.lock();
        try {
            cache.put(key, value);
        } finally {
            lock.unlock();
        }
    }
    
    public V getOrCompute(K key, ValueProvider<V> provider) {
        V value;
        // 首先尝试不加锁读取
        value = cache.get(key);
        if (value != null) {
            return value;
        }
        
        // 读取失败，加锁后再次尝试
        lock.lock();
        try {
            // 双重检查
            value = cache.get(key);
            if (value == null) {
                // 计算值并存储
                value = provider.provide();
                cache.put(key, value);
            }
            return value;
        } finally {
            lock.unlock();
        }
    }
    
    // 值提供者接口
    public interface ValueProvider<V> {
        V provide();
    }
    
    // 清除缓存
    public void clear() {
        lock.lock();
        try {
            cache.clear();
        } finally {
            lock.unlock();
        }
    }
    
    // 获取缓存大小
    public int size() {
        lock.lock();
        try {
            return cache.size();
        } finally {
            lock.unlock();
        }
    }
    
    public static void main(String[] args) {
        ConcurrentCache<String, String> cache = new ConcurrentCache<>();
        
        // 多线程测试
        Runnable cacheTask = () -> {
            String threadName = Thread.currentThread().getName();
            // 测试getOrCompute
            String value = cache.getOrCompute("key-" + (threadName.hashCode() % 10), 
                () -> {
                    System.out.println(threadName + " 计算值...");
                    try {
                        Thread.sleep(100); // 模拟计算耗时
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                    return "value-" + threadName;
                });
            
            System.out.println(threadName + " 获取到值: " + value);
        };
        
        // 创建并启动20个线程
        Thread[] threads = new Thread[20];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(cacheTask, "线程-" + i);
            threads[i].start();
        }
        
        // 等待所有线程完成
        for (Thread thread : threads) {
            try {
                thread.join();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        
        System.out.println("缓存大小: " + cache.size());
    }
}</code></pre>
            </div>
            
            <h3>4.2 实现分段锁提高并发度</h3>
            <div class="code-block mt-6 mb-8">
                <button class="copy-btn" onclick="copyCode(this)"><i class="fas fa-copy"></i></button>
                <pre><code>import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

public class SegmentedMap<K, V> {
    // 分段数量
    private final int segmentCount;
    // 每个段使用一个锁
    private final ReentrantLock[] locks;
    // 每个段一个Map
    private final Map<K, V>[] segments;
    
    @SuppressWarnings("unchecked")
    public SegmentedMap(int segmentCount) {
        this.segmentCount = segmentCount;
        this.locks = new ReentrantLock[segmentCount];
        this.segments = new Map[segmentCount];
        
        for (int i = 0; i < segmentCount; i++) {
            locks[i] = new ReentrantLock();
            segments[i] = new HashMap<>();
        }
    }
    
    // 计算key应该在哪个段
    private int segmentFor(K key) {
        return Math.abs(key.hashCode() % segmentCount);
    }
    
    public V get(K key) {
        int segmentIndex = segmentFor(key);
        locks[segmentIndex].lock();
        try {
            return segments[segmentIndex].get(key);
        } finally {
            locks[segmentIndex].unlock();
        }
    }
    
    public V put(K key, V value) {
        int segmentIndex = segmentFor(key);
        locks[segmentIndex].lock();
        try {
            return segments[segmentIndex].put(key, value);
        } finally {
            locks[segmentIndex].unlock();
        }
    }
    
    public V remove(K key) {
        int segmentIndex = segmentFor(key);
        locks[segmentIndex].lock();
        try {
            return segments[segmentIndex].remove(key);
        } finally {
            locks[segmentIndex].unlock();
        }
    }
    
    public int size() {
        int size = 0;
        // 获取所有锁
        for (ReentrantLock lock : locks) {
            lock.lock();
        }
        try {
            // 计算总大小
            for (Map<K, V> segment : segments) {
                size += segment.size();
            }
            return size;
        } finally {
            // 释放所有锁
            for (ReentrantLock lock : locks) {
                lock.unlock();
            }
        }
    }
    
    public static void main(String[] args) {
        final int SEGMENT_COUNT = 16;
        final int THREAD_COUNT = 100;
        final int OPERATIONS_PER_THREAD = 1000;
        
        SegmentedMap<String, Integer> map = new SegmentedMap<>(SEGMENT_COUNT);
        
        // 创建并启动写线程
        Thread[] threads = new Thread[THREAD_COUNT];
        for (int i = 0; i < THREAD_COUNT; i++) {
            final int threadNum = i;
            threads[i] = new Thread(() -> {
                for (int j = 0; j < OPERATIONS_PER_THREAD; j++) {
                    String key = "key-" + threadNum + "-" + j;
                    map.put(key, j);
                }
            });
            threads[i].start();
        }
        
        // 等待所有线程完成
        for (Thread thread : threads) {
            try {
                thread.join();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        
        System.out.println("Map 大小: " + map.size());
        System.out.println("期望大小: " + (THREAD_COUNT * OPERATIONS_PER_THREAD));
    }
}</code></pre>
            </div>
        </section>

        <!-- Section 5: Best Practices -->
        <section id="best-practices" class="content-card">
            <h2>五、使用 ReentrantLock 最佳实践</h2>
            
            <h3>5.1 锁使用规范</h3>
            <div class="grid md:grid-cols-2 gap-6">
                <div>
                    <h4>1. 始终在 try-finally 块中释放锁</h4>
                    <div class="code-block mt-2">
                        <button class="copy-btn" onclick="copyCode(this)"><i class="fas fa-copy"></i></button>
                        <pre><code>lock.lock();
try {
    // 临界区代码
} finally {
    lock.unlock();
}</code></pre>
                    </div>
                </div>
                <div>
                    <h4>2. 避免在临界区中执行耗时操作</h4>
                    <div class="code-block mt-2">
                        <button class="copy-btn" onclick="copyCode(this)"><i class="fas fa-copy"></i></button>
                        <pre><code>Data data;
lock.lock();
try {
    data = prepareData();
} finally {
    lock.unlock();
}
// 锁外执行耗时操作
processData(data);</code></pre>
                    </div>
                </div>
            </div>
            
            <h3 class="mt-8">5.2 性能优化技巧</h3>
            <div class="grid md:grid-cols-3 gap-4 mt-4">
                <div class="p-4 border border-gray-200 rounded-lg">
                    <h4 class="text-purple-600"><i class="fas fa-book-reader mr-2"></i>读写锁</h4>
                    <p>对于读多写少的场景，考虑使用 ReadWriteLock 代替 ReentrantLock</p>
                </div>
                <div class="p-4 border border-gray-200 rounded-lg">
                    <h4 class="text-purple-600"><i class="fas fa-clock mr-2"></i>tryLock</h4>
                    <p>在需要获取多个锁的情况下，使用 tryLock 可以避免死锁</p>
                </div>
                <div class="p-4 border border-gray-200 rounded-lg">
                    <h4 class="text-purple-600"><i class="fas fa-puzzle-piece mr-2"></i>分段锁</h4>
                    <p>尽量减少线程对同一把锁的竞争，例如使用分段锁</p>
                </div>
            </div>
            
            <h3 class="mt-8">5.3 常见陷阱与解决方案</h3>
            <div class="overflow-x-auto mt-4">
                <table class="comparison-table">
                    <thead>
                        <tr>
                            <th>陷阱</th>
                            <th>表现</th>
                            <th>解决方案</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>忘记释放锁</td>
                            <td>线程永远持有锁，其他线程无法获取</td>
                            <td>确保在 finally 块中释放锁</td>
                        </tr>
                        <tr>
                            <td>重入导致的性能问题</td>
                            <td>锁被同一个线程多次获取，影响吞吐量</td>
                            <td>审查代码确保不会过度重入</td>
                        </tr>
                        <tr>
                            <td>死锁</td>
                            <td>多个线程互相等待对方释放锁</td>
                            <td>固定锁的获取顺序，使用 tryLock</td>
                        </tr>
                        <tr>
                            <td>活锁</td>
                            <td>线程不断重试但始终无法取得进展</td>
                            <td>引入随机退避机制</td>
                        </tr>
                        <tr>
                            <td>线程饥饿</td>
                            <td>某些线程长时间无法获取锁</td>
                            <td>考虑使用公平锁</td>
                        </tr>
                    </tbody>
                </table>
            </div>
            
            <div class="mt-8 p-6 bg-purple-50 border border-purple-200 rounded-lg">
                <h3 class="text-purple-700"><i class="fas fa-lightbulb mr-2"></i>专家建议</h3>
                <p class="mt-2">在大多数场景下，非公平锁提供的性能优势远大于公平锁的公平性保证。除非有明确的公平性需求，否则优先选择非公平锁。</p>
                <p class="mt-2">对于高并发应用，考虑使用更高级的并发工具如 ConcurrentHashMap、ConcurrentLinkedQueue 等，它们内部已经实现了高效的并发控制。</p>
            </div>
        </section>
    </div>

    <!-- Footer -->
    <footer>
        <div class="footer-content">
            <div class="flex flex-col md:flex-row justify-between items-center">
                <div class="mb-4 md:mb-0">
                    <h3 class="text-xl font-bold mb-2">技术小馆</h3>
                    <p class="text-gray-400">专注于Java技术深度解析</p>
                </div>
                <div>
                    <a href="http://www.yuque.com/jtostring" class="footer-link hover:text-white">
                        <i class="fas fa-globe mr-2"></i>http://www.yuque.com/jtostring
                    </a>
                </div>
            </div>
            <div class="border-t border-gray-700 mt-8 pt-8 text-center text-gray-400">
                <p>© 2023 技术小馆. 保留所有权利.</p>
            </div>
        </div>
    </footer>

    <!-- Scroll to Top Button -->
    <div id="scrollTop" class="scroll-top">
        <i class="fas fa-arrow-up"></i>
    </div>

    <script>
        // 初始化 Mermaid
        mermaid.initialize({
            startOnLoad: true,
            theme: 'default',
            flowchart: {
                useMaxWidth: false,
                htmlLabels: true,
                curve: 'basis'
            }
        });
        
        // 复制代码功能
        function copyCode(button) {
            const codeBlock = button.nextElementSibling;
            const range = document.createRange();
            range.selectNode(codeBlock);
            window.getSelection().removeAllRanges();
            window.getSelection().addRange(range);
            document.execCommand('copy');
            window.getSelection().removeAllRanges();
            
            // 显示复制成功反馈
            const originalText = button.innerHTML;
            button.innerHTML = '<i class="fas fa-check"></i>';
            setTimeout(() => {
                button.innerHTML = originalText;
            }, 2000);
        }
        
        // 滚动到顶部按钮
        const scrollTopButton = document.getElementById('scrollTop');
        
        window.addEventListener('scroll', () => {
            if (window.pageYOffset > 300) {
                scrollTopButton.classList.add('visible');
            } else {
                scrollTopButton.classList.remove('visible');
            }
        });
        
        scrollTopButton.addEventListener('click', () => {
            window.scrollTo({
                top: 0,
                behavior: 'smooth'
            });
        });
        
        // 导航栏高亮
        const sections = document.querySelectorAll('section');
        const navItems = document.querySelectorAll('.nav-item');
        
        window.addEventListener('scroll', () => {
            let current = '';
            
            sections.forEach(section => {
                const sectionTop = section.offsetTop;
                const sectionHeight = section.clientHeight;
                
                if (pageYOffset >= sectionTop - 100) {
                    current = section.getAttribute('id');
                }
            });
            
            navItems.forEach(item => {
                item.classList.remove('active-nav');
                if (item.getAttribute('href') === `#${current}`) {
                    item.classList.add('active-nav');
                }
            });
        });
    </script>
</body>
</html>